package com.sc.service.impl;

import com.mybatisflex.core.update.UpdateChain;
import com.mybatisflex.spring.service.impl.CacheableServiceImpl;
import com.sc.dto.ScheduleBatchInsertDTO;
import com.sc.entity.TeachingSchedules;
import com.sc.mapper.TeachingSchedulesMapper;
import com.sc.service.TeachingSchedulesService;
import org.springframework.stereotype.Service;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;

/**
 * 授课时间表 服务层实现。
 *
 * @author JoeZhou
 * @since 2024-09-14
 */
@Service
@CacheConfig(cacheNames = "teachingSchedules")
public class TeachingSchedulesServiceImpl extends CacheableServiceImpl<TeachingSchedulesMapper, TeachingSchedules> implements TeachingSchedulesService {

    @Override
    @CacheEvict(allEntries = true)
    public boolean remove(QueryWrapper query) {
        return super.remove(query);
    }

    @Override
    @CacheEvict(allEntries = true)
    public boolean removeById(Serializable id) {
        return super.removeById(id);
    }

    @Override
    @CacheEvict(allEntries = true)
    public boolean removeByIds(Collection<? extends Serializable> ids) {
        return super.removeByIds(ids);
    }

    @Override
    @CacheEvict(allEntries = true)
    public boolean update(TeachingSchedules entity, QueryWrapper query) {
        return super.update(entity, query);
    }

    @Override
    @CacheEvict(allEntries = true)
    public boolean save(TeachingSchedules entity) {
        return super.save(entity);
    }

    @Override
    @Transactional
    @CacheEvict(allEntries = true)
    public boolean saveBatch(ScheduleBatchInsertDTO dto) {
        List<TeachingSchedules> list = new ArrayList<>();
        DayOfWeek dayOfWeek = DayOfWeek.of(dto.getDayOfWeek());
        System.out.println(dayOfWeek);
        // 上课日期
        LocalDate classDate = LocalDate.of(dto.getBeginDate().getYear(), dto.getBeginDate().getMonth(), dto.getBeginDate().getDayOfMonth());

        // 找到第一次排课的日期
        while (classDate.getDayOfWeek() != dayOfWeek) {
            classDate = classDate.plusDays(1);
        }
        for (int i = 0; i < dto.getNumberOfWeeks(); i++) {
            TeachingSchedules schedule = new TeachingSchedules();
            schedule.setCourseId(dto.getCourseId());
            // 算出开始时间和结束
            schedule.setStartTime(LocalDateTime.of(classDate.getYear(), classDate.getMonth(), classDate.getDayOfMonth(), dto.getStartTime().getHour(), dto.getStartTime().getMinute()));
            schedule.setEndTime(LocalDateTime.of(classDate.getYear(), classDate.getMonth(), classDate.getDayOfMonth(), dto.getEndTime().getHour(), dto.getEndTime().getMinute()));
            schedule.setHours(dto.getHours());
            schedule.setInfo(dto.getInfo());
            list.add(schedule);
            // 下一周
            classDate = classDate.plusDays(7);
        }
        return this.saveBatch(list);
    }

    @Override
    @CacheEvict(allEntries = true)
    public boolean updateById(TeachingSchedules entity, boolean ignoreNulls) {
        return super.updateById(entity, ignoreNulls);
    }

    @Override
    @CacheEvict(allEntries = true)
    public boolean updateBatch(Collection<TeachingSchedules> entities, int batchSize) {
        return super.updateBatch(entities, batchSize);
    }

    @Override
    @Cacheable(key = "#id")
    public TeachingSchedules getById(Serializable id) {
        return super.getById(id);
    }

    @Override
    @Cacheable(key = "#root.methodName + ':' + #query.toSQL()")
    public TeachingSchedules getOne(QueryWrapper query) {
        return super.getOne(query);
    }

    @Override
    @Cacheable(key = "#root.methodName + ':' + #query.toSQL()")
    public <R> R getOneAs(QueryWrapper query, Class<R> asType) {
        return super.getOneAs(query, asType);
    }

    @Override
    @Cacheable(key = "#root.methodName + ':' + #query.toSQL()")
    public Object getObj(QueryWrapper query) {
        return super.getObj(query);
    }

    @Override
    @Cacheable(key = "#root.methodName + ':' + #query.toSQL()")
    public <R> R getObjAs(QueryWrapper query, Class<R> asType) {
        return super.getObjAs(query, asType);
    }

    @Override
    @Cacheable(key = "#root.methodName + ':' + #query.toSQL()")
    public List<Object> objList(QueryWrapper query) {
        return super.objList(query);
    }

    @Override
    @Cacheable(key = "#root.methodName + ':' + #query.toSQL()")
    public <R> List<R> objListAs(QueryWrapper query, Class<R> asType) {
        return super.objListAs(query, asType);
    }

    @Override
    @Cacheable(key = "#root.methodName + ':' + #query.toSQL()")
    public List<TeachingSchedules> list(QueryWrapper query) {
        return super.list(query);
    }

    @Override
    @Cacheable(key = "#root.methodName + ':' + #query.toSQL()")
    public <R> List<R> listAs(QueryWrapper query, Class<R> asType) {
        return super.listAs(query, asType);
    }

    /**
     * @deprecated 无法通过注解进行缓存操作。
     */
    @Override
    @Deprecated
    public List<TeachingSchedules> listByIds(Collection<? extends Serializable> ids) {
        return super.listByIds(ids);
    }

    @Override
    @Cacheable(key = "#root.methodName + ':' + #query.toSQL()")
    public long count(QueryWrapper query) {
        return super.count(query);
    }

    @Override
    @Cacheable(key = "#root.methodName + ':' + #page.getPageSize() + ':' + #page.getPageNumber() + ':' + #query.toSQL()")
    public <R> Page<R> pageAs(Page<R> page, QueryWrapper query, Class<R> asType) {
        return super.pageAs(page, query, asType);
    }

    @Override
    @CacheEvict
    public boolean refreshStatusByCourseId(Long courseId) {
        // 结束时间大于当前系统时间的排课状态改为已结束
        UpdateChain.of(TeachingSchedules.class)
                .set(TeachingSchedules::getStatus, 2)
                .where(TeachingSchedules::getCourseId).eq(courseId)
                .where(TeachingSchedules::getEndTime).lt(LocalDateTime.now())
                .update();
        // 开始时间小于当前系统时间且结束时间大于当前系统时间的排课状态改为正在进行
        UpdateChain.of(TeachingSchedules.class)
                .set(TeachingSchedules::getStatus, 1)
                .where(TeachingSchedules::getCourseId).eq(courseId)
                .where(TeachingSchedules::getStartTime).lt(LocalDateTime.now())
                .where(TeachingSchedules::getEndTime).gt(LocalDateTime.now())
                .update();
        return true;
    }

}
